package cn.bud.msgbus.consumer.client;

import com.zl9c.general.bus.client.provider.ProviderHandler;
import com.zl9c.general.bus.client.provider.ProviderProxy;
import com.zl9c.general.bus.client.provider.SubscribeProvideClient;
import org.springframework.context.annotation.DependsOn;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * BusProviderScaner
 *
 * @author hxj
 * @version 1.0
 * @description
 * @date 2024-07-15 8:59
 */
@DependsOn("zl9cApplicationContext")
@Component
public class BusProviderScanner {
    @javax.annotation.Resource
    private ProviderHandler providerHandler;


    String[] scanPackages = new String[]{"com.zl9c.bus.**.provider"};



    public List<ProviderProxy> scanProviders(String... scanPackages) throws IOException, ClassNotFoundException {
        List<ProviderProxy> proxies = new ArrayList<>();
        for (String scanPackage : scanPackages) {
            List<Class<?>> clazzList = scanProviderClazzList(scanPackage);
            for (Class<?> clazz : clazzList) {
                ProviderProxy proxy = new ProviderProxy(clazz, providerHandler);
                providerHandler.addProxy(proxy);
                proxies.add(proxy);
            }
        }
        return proxies;
    }

    public List<Class<?>> scanProviderClazzList(String packagePath) throws IOException, ClassNotFoundException {
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
                + ClassUtils.convertClassNameToResourcePath(packagePath) + "/*.class";
//    以上代码可解析出当前工程所引用的jar包中的类
//    以下代码却不可以解析jar中的类，本地IDEA中测试没有问题，工程里直接引用的sub module, 但Linux上就找不着了
//     Resource[] resources = resolver.getResources("classpath*:org\\yourpackage\\*.class");
//     Resource[] resources = resolver.getResources("classpath*:"+packagePath+"\\*.class");

        Resource[] resources = resolver.getResources(pattern);
        CachingMetadataReaderFactory readerFactory = new CachingMetadataReaderFactory();

//     ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();

        List<Class<?>> list = new ArrayList<>();
        for (Resource resource : resources) {
            //全限定类名，完整路径
            String className = readerFactory.getMetadataReader(resource).getClassMetadata().getClassName();
//         Class<?> aClass = systemClassLoader.loadClass(className); //在linux上是出现找不到类的异常，并不是由这个ClassLoader加载的
            Class<?> aClass = Class.forName(className);//直接使用Class.forName 即可加载出来
            if ( aClass.isAnnotationPresent(SubscribeProvideClient.class)) {
                list.add(aClass);
            }
        }
        return list;
    }

}
